﻿using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using RQX.Common.Web.Tools;
using RQX.Common.Web.Web.Container;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Loader;

namespace RQX.Common.Web.Web.Startup
{
    public static class ServiceExtension
    {
        public static T GetSingletonInstanceOrNull<T>(this IServiceCollection services)
        {
            return (T)services.FirstOrDefault(k => k.ServiceType == typeof(T))?.ImplementationInstance;
        }

        public static T GetSingletonInstance<T>(this IServiceCollection services)
        {
            var instance = services.GetSingletonInstanceOrNull<T>();
            if (instance == null)
            {
                throw new InvalidOperationException("Could not find singleton service: " + typeof(T).AssemblyQualifiedName);
            }
            return instance;
        }

        private static IEnumerable<string> FilterNotNeedContainerDll(string[] pathList)
        {
            string[] filterList =
            {
                "\\api-",
                "\\aspnetcore",
                "\\AutoMapper.",
                "\\clrcompression.",
                "\\clretwrc.",
                "\\clrjit.",
                "\\coreclr.",
                "\\dbgshim.",
                "\\hostfxr.",
                "\\hostpolicy.",
                "\\Microsoft.",
                "\\mscor",
                "\\netstandard",
                "\\Newtonsoft.",
                "\\sni.",
                "\\Swashbuckle.",
                "\\System.",
                "\\ucrtbase.",
                "\\WindowsBase.",
            };
            return pathList.Where(k => !k.Contains(filterList));
        }


        public static void AddContainers(this IServiceCollection services)
        {
            var pathFiles = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll", SearchOption.AllDirectories);
            var files = FilterNotNeedContainerDll(pathFiles);
            foreach (var file in files)
            {
                using (var fs = new FileStream(file, FileMode.Open, FileAccess.Read))
                {
                    var assembly = new AssemblyLoadContext(Guid.NewGuid().ToString("N"), true).LoadFromStream(fs);
                    // k.GetInterfaces().Contains(typeof(IBaseService))
                    var typeList = assembly.GetTypes().Where(k => (typeof(IIoCManager)).IsAssignableFrom(k.FullName.GetCurrentType())
                    && k.IsClass
                    && !k.IsInterface
                    && !k.IsEnum
                    && !k.IsAbstract);
                    foreach (var type in typeList)
                    {
                        var typeObj = type.FullName.GetCurrentType();
                        services.AddScoped(typeObj);
                    }
                }
            }
            services.AddIocAttributeServices();
        }
        public static void AllowSyncIO(this IServiceCollection services)
        {
            services.Configure<IISServerOptions>(option =>
            {
                option.AllowSynchronousIO = true;
            });
        }

        public static void AddNewtonsoftJson(this IMvcBuilder mvcBuilder)
        {
            mvcBuilder.AddNewtonsoftJson(options =>
            {
                options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
                options.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Local;
                options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
            });
        }
    }
}
